/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.yonsei.iwb.smarttv.gui;

import com.hp.hpl.jena.rdf.model.Resource;
import edu.uci.ics.jung.algorithms.layout.CircleLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.UndirectedSparseMultigraph;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.AbstractEdgeShapeTransformer;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.renderers.EdgeLabelRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;
import edu.yonsei.iwb.smarttv.model.ConceptArc;
import edu.yonsei.iwb.smarttv.model.MArc;
import edu.yonsei.iwb.smarttv.querygraph.algorithm.ShortestPath;
import edu.yonsei.iwb.smarttv.querygraph.algorithm.ShortestPathVectorCandidateSet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JPanel;
import org.apache.commons.collections15.Transformer;

/**
 *
 * @author Joo
 */
public class ShortestPathView {
    private ShortestPathVectorCandidateSet candidateSP;
    private Vector<JPanel> shortestPathView;
    
    
    public ShortestPathView(ShortestPathVectorCandidateSet candidateSP) {
          this.candidateSP = (ShortestPathVectorCandidateSet)candidateSP.clone();
          
    }
    
    public Vector<JPanel> generateShortestPathView() {
        shortestPathView = new Vector<JPanel>();
        int numberOfVertex = 0;
        int numberOfEdge = 0;
        for(int i = 0 ; i < candidateSP.size(); i ++) {
//            Graph<VisVertex, VisEdge> g = new DirectedSparseMultigraph<VisVertex, VisEdge>();
            Graph<VisVertex, VisEdge> g = new UndirectedSparseMultigraph<VisVertex, VisEdge>();
            Hashtable<String, VisVertex> vertexInfo = new Hashtable<String, VisVertex>();
            Iterator<ConceptArc> it = candidateSP.get(i).keySet().iterator();
            Vector<ConceptArc> arcSet = new Vector<ConceptArc>();
            Vector<ShortestPath> arcValueSet = new Vector<ShortestPath>();
            while(it.hasNext()) {
                arcSet.add(it.next());
            }
            // 인스턴스가 없는 노드에 ""를 넣음
            for(int j = 0; j < arcSet.size(); j++) {
                if(arcSet.get(j).getHead().getInstance()==null) {
                    arcSet.get(j).getHead().setInstanceURI("");
                } else if (arcSet.get(j).getTail().getInstance()==null) {
                    arcSet.get(j).getTail().setInstanceURI("");
                }
            }
            // 컨셉아크의 머리와 꼬리를 노드인포에 넣고 키노드로 표시
            for(int j = 0; j < arcSet.size(); j++) {
                arcValueSet.add(candidateSP.get(i).get(arcSet.get(j)));
                if(!vertexInfo.containsKey(arcSet.get(j).getHead().getNode().getURI() + arcSet.get(j).getHead().getInstanceURI())) {
                    VisVertex v1;
                    if(arcSet.get(j).getHead().getInstance()==null) {
                        v1 = new VisVertex(numberOfVertex, arcSet.get(j).getHead().getNode().getURI());
                        v1.setIsKeyVertex();
                    } else {
                        v1 = new VisVertex(numberOfVertex, arcSet.get(j).getHead().getNode().getURI(), arcSet.get(j).getHead().getInstance().getURI());
                        v1.setIsKeyVertex();
                    }
                    numberOfVertex++;
                    vertexInfo.put(arcSet.get(j).getHead().getNode().getURI()+arcSet.get(j).getHead().getInstanceURI(), v1);
                    g.addVertex(v1);
                }

                if(!vertexInfo.containsKey(arcSet.get(j).getTail().getNode().getURI()+arcSet.get(j).getTail().getInstanceURI())) {
                    VisVertex v2;
                    if(arcSet.get(j).getTail().getInstance()==null) {
                        v2 = new VisVertex(numberOfVertex, arcSet.get(j).getTail().getNode().getURI());
                        v2.setIsKeyVertex();
                    } else {
                        v2 = new VisVertex(numberOfVertex, arcSet.get(j).getTail().getNode().getURI(), arcSet.get(j).getTail().getInstance().getURI());
                        v2.setIsKeyVertex();
                    }
                    numberOfVertex++;
                    vertexInfo.put(arcSet.get(j).getTail().getNode().getURI() + arcSet.get(j).getTail().getInstanceURI(), v2);
                    g.addVertex(v2);
                }                    
            }
            
            //arcSet = concept arc set
            //arcValueSet = shortest path set
            
            for(int k = 0; k < arcValueSet.size(); k++) {
                ShortestPath sp = arcValueSet.get(k);
                
                MArc firstArc = sp.firstElement();
                VisVertex first = vertexInfo.get(arcSet.get(k).getHead().getNode().getURI()+arcSet.get(k).getHead().getInstanceURI());
                VisVertex tempTail = new VisVertex(numberOfVertex++, firstArc.getTailNode().getName());
                VisEdge efirst = new VisEdge(numberOfEdge, firstArc.getProperty().toString(), first, tempTail);
                g.addEdge(efirst, first, tempTail);
                numberOfEdge++;
                
                for (int j = 1; j < sp.size()-1; j++) {
                    MArc arc = sp.get(j);
                    VisVertex tempmidHead = new VisVertex(numberOfVertex++, arc.getHeadNode().getName());
                    VisVertex tempmidTail = new VisVertex(numberOfVertex++, arc.getTailNode().getName());
                    VisEdge tempEdge = new VisEdge(numberOfEdge, arc.getProperty().toString(), tempmidHead, tempmidTail);
                    g.addEdge(tempEdge, tempmidHead, tempmidTail);
                    numberOfEdge++;
                }
                
                MArc lastArc = sp.lastElement();
                VisVertex lastHead = new VisVertex(numberOfVertex++, lastArc.getHeadNode().getName());
                VisVertex last = vertexInfo.get(arcSet.get(k).getTail().getNode().getURI()+arcSet.get(k).getTail().getInstanceURI());                
                VisEdge elast = new VisEdge(numberOfEdge, lastArc.getProperty().toString(), lastHead, last);
                g.addEdge(elast, lastHead, last);
                numberOfEdge++;                                
            }

//            Layout<VisVertex, VisEdge> layout = new FRLayout<VisVertex, VisEdge>(g);
            Layout<VisVertex, VisEdge> layout = new CircleLayout(g);
//            layout.setSize(new Dimension(400, 400));
            layout.setSize(new Dimension(300, 300));
        
            VisualizationViewer<VisVertex, VisEdge> vv = new VisualizationViewer<VisVertex, VisEdge>(layout);
            vv.setPreferredSize(new Dimension(350, 350));
            DefaultModalGraphMouse gm = new DefaultModalGraphMouse();
            gm.setMode(ModalGraphMouse.Mode.TRANSFORMING);
            vv.setGraphMouse(gm);
            vv.addKeyListener(gm.getModeKeyListener());
        
            Transformer<VisVertex, Shape> vertexShape = new Transformer<VisVertex, Shape>() {
                public Shape transform(VisVertex v) {
                    String temp = v.toString();
                    int num;
                    if(v.isInstance()){
                        num = temp.length()*4;
                    }else{
                        num = temp.length()*10;
                    }
                    return new Ellipse2D.Double(-25, -10, num, 35);
                }
            }; 
        
            Transformer<VisVertex, Paint> vertexPaint = new Transformer<VisVertex, Paint>() {
                public Paint transform(VisVertex v) {
                    if(v.isKeyVertex()) {
                        return Color.RED;
                    } else {
                        return Color.GREEN;
                    }
                }
            };
        
            EdgeLabelRenderer edgeLabelRenderer = vv.getRenderContext().getEdgeLabelRenderer();
        
            Transformer<VisEdge,String> edgeStringer = new Transformer<VisEdge,String>(){
                public String transform(VisEdge e) {
                    return e.toString();
                }
            };
          
            vv.getRenderContext().setVertexShapeTransformer(vertexShape);
            vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);
            vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
            vv.getRenderContext().setEdgeLabelTransformer(edgeStringer);
            vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.QuadCurve<VisVertex,VisEdge>());
            vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
//            vv.getRenderContext().setLabelOffset(20);
            AbstractEdgeShapeTransformer<VisVertex,VisEdge> aesf = (AbstractEdgeShapeTransformer<VisVertex,VisEdge>)vv.getRenderContext().getEdgeShapeTransformer();
            aesf.setControlOffsetIncrement(35);
            
            shortestPathView.add(vv);    
        }    
        return shortestPathView;
    }
    
}
